﻿#include "smalltool.h"

SmallTool::SmallTool(QObject *parent) : QObject(parent)
{
}

void SmallTool::parseFile(QString path)
{
    //"PF_Common.h"

    qInfo()<<"readFile 开始解析头文件"<<path;

    _parseHeadMsgList.clear();
    _value = 0;

    //
    QFile file(path);
    QString fileData;
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        fileData = "";
        qInfo()<<"readFile faile. "<<path;
        return;
    }
    QTextStream in(&file);

    while (!in.atEnd()) {
        QString line = in.readLine();
        process_line(line);
    }
    file.close();

    //set parse
    qInfo()<<__FUNCTION__<<_parseHeadMsgList[0]<<"\n";

    //进行匹配，合成一个数据
    int len = _nameToIdList.length();
    for(int i=0; i<len;i++){
        QString nameSr = _nameToIdList.at(i).toMap().value("name").toString();
        int id = _nameToIdList.at(i).toMap().value("id").toInt();

        //为了和enum id相匹配，优化处理name内容
        //MSG_EEPROM_0_ID -> EEPROM_0
        QString name = nameSr;
        name = name.replace("MSG_", "").replace("_ID", "").trimmed();

        int l = _parseHeadMsgList.length();
        for(int j=0; j<l;j++){

            QVariantMap m = _parseHeadMsgList.at(j).toMap();
            QString fromName = m.value("name").toString();

            //为了和enum id相匹配，优化处理name内容
            //_c_MSG_EEPROM_0_msgType => EEPROM_0
            //_c_ICGM_IBDU_5E1h_IP_msgType => ICGM_IBDU_5E1h
            //_c_MSG_MCU_4_msgType => MCU_4
            fromName = fromName.replace("_c_MSG_", "").replace("_c_", "").replace("_IP_msgType", "").replace("_msgType", "");

            if(name.contains(fromName)){
                m.insert("id", id);
                m.insert("idEnum", nameSr);
                _parseHeadMsgList[j] = m;
                continue;
            }
        }
    }

    emit sendParseResult(_parseHeadMsgList);

    createDynamicHeader();      //动态生成dynamic_create.h
}

void SmallTool::process_line(QString line)
{
    //    qInfo()<<__FUNCTION__<<line;
    //解析id枚举内容
    if(line.contains("typedef enum") && _start_flag != "RpcMsgId"){
        _start_flag = "enum";
    }
    if(_start_flag == "enum" && line.contains("MSG_")){
        if(line.trimmed().startsWith("//")) return;
        QString _line = line.split(",")[0];
        QString name;
        if(_line.contains("=")){
            //有值
            QStringList l = _line.split("=");
            name = QString(l.at(0)).trimmed();
            _value = QString(l.at(1)).toInt(nullptr, 16);
        }
        else{
            _value += 1;
            name = _line.trimmed();
        }
        QVariantMap m;
        m.insert("name", name);
        m.insert("id", _value);
        _nameToIdList.append(m);

    }
    if(_start_flag == "enum" && line.contains("RpcMsgId")){
        _start_flag = "RpcMsgId";
//       qInfo()<<"+++"<<_nameToIdList;
    }


    //解析结构体内容
    if(line.contains("typedef union")){
        //start
        _start_flag = "union";
        _msg.clear();
        _msgList.clear();
    }

    if(_start_flag == "union" && line.contains("struct")){
        _start_flag = "struct";
    }
    else if(_start_flag == "struct" && line.contains("Type_")){
        _start_flag = "struct";
        //正则

        QString _line = line.replace("\t", " ").trimmed();
        QRegExp rx("Type_.* (.*);");
        rx.setMinimal(true);
        int count = 0;
        int pos = 0;
        QString result = "";
        while((pos = rx.indexIn(_line.trimmed(), pos)) != -1){
            ++count;
            pos += rx.matchedLength();

            result = rx.cap(1);
            break;
        }

        //        qInfo()<<"正则struct"<<_line<<result;
        if(result.isEmpty()) return;

        QString name, bits;
        //        result = result.replace("\t", " ").trimmed();
        //        qInfo()<<"正则2 struct"<<_line<<result;
        if(result.contains(":")){            
            name = QString(result.split(":")[0]).trimmed();
            bits = QString(result.split(":")[1]).trimmed();

//            if(result.contains("Type_uHWord")){
//                bits =  (int)(bits.toInt() / sizeof(Type_uHWord)*8) + 1;
//            }
        }
        else{
            name = result;
            if(line.contains("Type_uHWord"))
                bits = "16";
            else if(line.contains("Type_uWord"))
                bits = "32";
            else if(line.contains("Type_uDWord"))
                bits = "64";
            else
                bits = "8";
        }

        QVariantMap m;
        m.insert("name", name);
        m.insert("bits", bits.toInt());
        m.insert("value", 0);
        _msgList.append(m);

    }
    else if(_start_flag == "struct" && line.contains("Signals")){
        _start_flag = "Signals";
    }
    else if(_start_flag == "Signals" && line.contains("msgType")){
        _start_flag = "msgType";
        //end

        QString result = line.trimmed().replace("}", "").replace(";", "");

        //        qInfo()<<"正则Signals========"<<line<<result;

        if(result.isEmpty()) return;

        result = result.trimmed();

        //为了和enum id相匹配，优化处理name内容
        //_c_MSG_EEPROM_0_msgType => EEPROM_0
        //_c_ICGM_IBDU_5E1h_IP_msgType => ICGM_IBDU_5E1h
        //_c_MSG_MCU_4_msgType => MCU_4
        //因为使用了动态生成代码,不用优化了
        result = result.trimmed();
        _msg.insert("id", -1);
        _msg.insert("name", result);
        _msg.insert("msgList", _msgList);

        //        qInfo()<<"正则Signals======rrrr=="<<_msg;

        _parseHeadMsgList.append(_msg);
    }
}

void SmallTool::writeFile(QString data, QString path)
{
    QFile file(path);
    if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qWarning()<<"无法写入文件!!!"<<path;
        return;
    }
    QTextStream out(&file);
    out << data;
    out.flush();
    file.close();
}

void SmallTool::createDynamicHeader()
{
    QString data;
    data += "#ifndef DYNAMIC_CREATE_H\n";
    data += "#define DYNAMIC_CREATE_H\n\n";

    data += "#include <QByteArray>\n";
    data += "#include <QVariant>\n";
    data += "#include \"PF_Common.h\"\n\n";

    data += "static QByteArray changeToba(int id, QVariant data, int& len){\n";
    data += "    QVariantList list = data.toList();\n";
    data += "    QByteArray byteArray;\n\n";

    data += "    switch (id) {\n";

    //这里要动态生成
    int len = _parseHeadMsgList.length();

    for(int j=0; j<len;j++){

        QVariantMap m = _parseHeadMsgList.at(j).toMap();
        QString idEnum = m.value("idEnum").toString();
        QString name = m.value("name").toString();

        if(idEnum.trimmed().isEmpty()) continue;

        data += QString("    case %1:\n").arg(idEnum);
        data += QString("        %1 msg%2;\n").arg(name).arg(j);
        data += QString("        len = sizeof(msg%1);\n").arg(j);

        QVariantList msgList = m.value("msgList").toList();

        int l = msgList.length();

        for(int k=0; k<l; k++){
            data += QString("        msg%1.Signals.%2 = list.at(%3).toMap().value(\"value\").toUInt();\n")
                    .arg(j).arg(msgList.at(k).toMap().value("name").toString()).arg(k);
        }

        data += "\n";
        data += QString("        byteArray = QByteArray((const char*)&msg%1, len);\n").arg(j);
        data += "        break;\n";

    }
//    data += "    case MSG_ICGM_IBDU_330h_ID:\n";
//    data += "        _c_ICGM_IBDU_330h_IP_msgType msg;\n";
//    data += "        msg.Signals.IsTimeout = list.at(0).toMap().value(\"value\").toUInt();\n";
//    data += "        len = sizeof(msg);\n";
//    data += "\n";
//    data += "        QByteArray byteArray;\n";
//    data += "        byteArray = QByteArray((const char*)&msg, len);\n";
//    data += "        return byteArray;\n";

    data += "    }\n";
    data += "\n";
    data += "    return byteArray;\n";
    data += "}\n";

    data += "#endif // DYNAMIC_CREATE_H";

    writeFile(data, "dynamic_create.h");
}

void SmallTool::checkPop()
{
    QMapIterator<int, QString> i(g_popList);
    while (i.hasNext()) {
        i.next();
        qInfo() << i.key() << ": " << i.value() << endl;

        if(ptPopupTbl[i.key()-1]->name != i.value()){
            qInfo()<<QString("ptPopupTbl错误,errorName key: %1, value: %2").arg(i.key()).arg(i.value());
        }
        if(ptPopupTbl[i.key()-1]->priorityvalue != i.key()){
            qInfo()<<QString("errorPriority key: %1, value: %2").arg(i.key()).arg(i.value());
        }
    }

}
QString SmallTool::readFile(QString path)
{
    QFile file(path);
    QString fileData;

    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        fileData = "";
        return fileData;
    }
    fileData = QString(file.readAll());
    file.close();

    return fileData;
}
